{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Transfer function matrices\n", "\n", "Let's say we have two inputs and two outputs. We can write the linearised effect as follows:\n", "\n", "\\begin{align}\n", "y_1 &= G_{11} u_1 + G_{12} u_2 \\\\\n", "y_2 &= G_{21} u_1 + G_{22} u_2\n", "\\end{align}\n", "\n", "Which is equivalent to a matrix expression\n", "\n", "$$\\mathbf{y} = G \\mathbf{u}$$\n", "\n", "with \n", "\n", "$$\\mathbf{y} = \\begin{bmatrix}y_1\\\\y_2\\end{bmatrix} \n", " \\quad G = \\begin{bmatrix}G_{11} & G_{12} \\\\ G_{21} & G_{22} \\end{bmatrix}\n", " \\quad \\mathbf{u} = \\begin{bmatrix}u_1\\\\u_2\\end{bmatrix}$$\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I find it useful to picture the input going into the top of the matrix and the output coming out of the side" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Representing matrices in SymPy" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import sympy\n", "sympy.init_printing()" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "s = sympy.Symbol('s')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "G11 = (s + 1)/(s + 2)\n", "G12 = 1/(2*s + 1)\n", "G21 = 1/(3*s + 1) \n", "G22 = 1/(4*s + 1)\n", "\n", "row1 = [G11, G12]\n", "row2 = [G21, G22]\n", "list_of_lists = [row1, \n", " row2]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "G = sympy.Matrix(list_of_lists)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAC4AAAAtCAYAAADRLVmZAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC4ElEQVRoBe2Z7VEjMQyGyc0VkDs6WDq4jw6gAyiBuw7gZ/KXdEAoATogLZAOoAMydJB7Xp/lWW92d7IZRMxMNOORLVv2G1mW18povV4flUzT6fQH+O4pP6m/GdavVimJA3AMnjvKivKLUlEycgPO4qesVMHn2YpbNKJlLzSU+hVMVs/oS9Z634aspuJCnsBdANukG67C1tzQ+RoHnMCv49aZThE8Aw7Axwh0KXS05af6IX/VLomSqwBSJ/cUHkBHkNfwp5IAG5bM4hICXFZX3FxQP5OsjxhzS792pknfJaC/bbeWyEPUaCpt2x7VLyAmk1so/BjNkMnqgwm9c5QUDmeDlWsK6AuPcH2jni6g5CoaS4cO4oiqLL2gXNF2C2nMvzMF4IC7oTzbLNS3chMbvw9uFpePylcTAV5bPYen7UmdH1s5jsuFM2NL2+G8RKCI8gdurvFGu+1gma4rZ20FCJEd/HtkL7Qf4fMAnIpCYD0MSmGvBKbeqGOu4gFSLubmZlk49EDvNaenxb0wh3kPwF3N2zL5weItRnEVfVqLjyaTSdn5iY59O8TxDsO4iT+tjx+Au/lEx8T2Pd7RvT8xn7UVq9t7V/nDldrxE/yoyKgSQd/CU5aBuj3kz6gv3Hycye1Ftcu2bSShmE/W1/d9eBm5AWcBPQFVdiE9154B29RX5mGMvPIEvgtg0xHAFwDKwm003jicDNY27TXpCYau92bIk9O/zIAjKDbpCTaBrigh0iRXoUNCHaj6a1+DSkl66lA+gC+k9FI4jMCVzZJ/WdJTeYxeQq836Ymy4m+TBiU94xrKQ6bwmIBrZjosVtpCJSQ9laRS7M78PrlKBF5U0hOwSgOe1EFTl+X/h0MqxSU9waTD+Btu175sK9KPWVlUUcAvJukpi4LHzlmGC7kCyMyAl5b0VFgWePl3k0LUC8D5BWrUw2Bz8Ie2waN/+3opO5y9I4d36rruurKHz9bQ+AdEMRJebgMeSgAAAABJRU5ErkJggg==\n", "text/latex": [ "$\\displaystyle \\frac{s + 1}{s + 2}$" ], "text/plain": [ "s + 1\n", "─────\n", "s + 2" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "G[0, 0]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}\\frac{6 s^{3} + 17 s^{2} + 11 s + 2}{6 s^{3} + 7 s^{2} - 3 s - 1} & - \\frac{12 s^{3} + 31 s^{2} + 15 s + 2}{6 s^{3} + 7 s^{2} - 3 s - 1}\\\\- \\frac{8 s^{3} + 22 s^{2} + 13 s + 2}{6 s^{3} + 7 s^{2} - 3 s - 1} & \\frac{24 s^{4} + 50 s^{3} + 35 s^{2} + 10 s + 1}{6 s^{3} + 7 s^{2} - 3 s - 1}\\end{matrix}\\right]$" ], "text/plain": [ "⎡ 3 2 ⎛ 3 2 ⎞ ⎤\n", "⎢ 6⋅s + 17⋅s + 11⋅s + 2 -⎝12⋅s + 31⋅s + 15⋅s + 2⎠ ⎥\n", "⎢ ─────────────────────── ──────────────────────────── ⎥\n", "⎢ 3 2 3 2 ⎥\n", "⎢ 6⋅s + 7⋅s - 3⋅s - 1 6⋅s + 7⋅s - 3⋅s - 1 ⎥\n", "⎢ ⎥\n", "⎢ ⎛ 3 2 ⎞ 4 3 2 ⎥\n", "⎢-⎝8⋅s + 22⋅s + 13⋅s + 2⎠ 24⋅s + 50⋅s + 35⋅s + 10⋅s + 1⎥\n", "⎢─────────────────────────── ────────────────────────────────⎥\n", "⎢ 3 2 3 2 ⎥\n", "⎣ 6⋅s + 7⋅s - 3⋅s - 1 6⋅s + 7⋅s - 3⋅s - 1 ⎦" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.simplify(G.inv())" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/latex": [ "$\\displaystyle \\left[\\begin{matrix}\\frac{2 \\left(s + 1\\right)}{s + 2} & \\frac{2}{2 s + 1}\\\\\\frac{2}{3 s + 1} & \\frac{2}{4 s + 1}\\end{matrix}\\right]$" ], "text/plain": [ "⎡2⋅(s + 1) 2 ⎤\n", "⎢───────── ───────⎥\n", "⎢ s + 2 2⋅s + 1⎥\n", "⎢ ⎥\n", "⎢ 2 2 ⎥\n", "⎢ ─────── ───────⎥\n", "⎣ 3⋅s + 1 4⋅s + 1⎦" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "G + G" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Representing matrices using the control library" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import control" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\frac{1}{s + 2}$$" ], "text/plain": [ "TransferFunction(array([1]), array([1, 2]))" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "control.tf([0, 1], [1, 2])" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "s = control.tf([1, 0], 1)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\frac{s}{1}$$" ], "text/plain": [ "TransferFunction(array([1, 0]), array([1]))" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "G = 1/(s + 1)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "num11 = [1, 2]\n", "num12 = [2]\n", "num21 = [3]\n", "num22 = [4]\n", "\n", "row1 = [num11, num12]\n", "row2 = [num21, num22]\n", "numerator = [row1, \n", " row2]\n", "\n", "\n", "denominator = [[[1, 1], [2, 1]], \n", " [[3, 1], [4, 1]]]\n", "Gmatrix = control.tf(numerator, \n", " denominator)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$$\\begin{bmatrix}\\frac{s + 2}{s + 1}&\\frac{2}{2 s + 1}\\\\\\frac{3}{3 s + 1}&\\frac{4}{4 s + 1}\\\\ \\end{bmatrix}$$" ], "text/plain": [ "TransferFunction([[array([1, 2]), array([2])], [array([3]), array([4])]], [[array([1, 1]), array([2, 1])], [array([3, 1]), array([4, 1])]])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Gmatrix" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conversion to state space" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "See the [state space notebook](State%20space.ipynb) for more information about conversion between state space and transfer function form. The examples in that notebook are for SISO transfer functions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are no tools in `scipy.signal` to deal with mutlivariable transfer functions. However, the control library can do the conversion from a transfer function matrix to a state space form if you have the [slycot]() library installed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can try to install slycot using this command:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "#!conda install -c conda-forge control slycot" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "\\[\n", "\\left(\n", "\\begin{array}{rllrllrllrll|rllrll}\n", "-1.&\\hspace{-1em}33&\\hspace{-1em}\\phantom{\\cdot}&-1.&\\hspace{-1em}11&\\hspace{-1em}\\cdot10^{-16}&-1.&\\hspace{-1em}67&\\hspace{-1em}\\cdot10^{-16}&-0.&\\hspace{-1em}333&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&-1.&\\hspace{-1em}11&\\hspace{-1em}\\cdot10^{-16}\\\\\n", "-3.&\\hspace{-1em}33&\\hspace{-1em}\\cdot10^{-16}&-0.&\\hspace{-1em}75&\\hspace{-1em}\\phantom{\\cdot}&-0.&\\hspace{-1em}125&\\hspace{-1em}\\phantom{\\cdot}&6.&\\hspace{-1em}94&\\hspace{-1em}\\cdot10^{-17}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n", "1.&\\hspace{-1em}11&\\hspace{-1em}\\cdot10^{-16}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&-2.&\\hspace{-1em}1&\\hspace{-1em}\\cdot10^{-16}&-3.&\\hspace{-1em}41&\\hspace{-1em}\\cdot10^{-16}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n", "1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&1.&\\hspace{-1em}31&\\hspace{-1em}\\cdot10^{-16}&-9.&\\hspace{-1em}52&\\hspace{-1em}\\cdot10^{-17}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n", "\\hline\n", "1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0.&\\hspace{-1em}25&\\hspace{-1em}\\phantom{\\cdot}&0.&\\hspace{-1em}333&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n", "1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0.&\\hspace{-1em}5&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n", "\\end{array}\\right)\n", "\\]" ], "text/plain": [ "StateSpace(array([[-1.33333333e+00, -1.11022302e-16, -1.66533454e-16,\n", " -3.33333333e-01],\n", " [-3.33066907e-16, -7.50000000e-01, -1.25000000e-01,\n", " 6.93889390e-17],\n", " [ 1.11022302e-16, 1.00000000e+00, -2.10075805e-16,\n", " -3.40587617e-16],\n", " [ 1.00000000e+00, 0.00000000e+00, 1.31257168e-16,\n", " -9.52355269e-17]]), array([[ 1.00000000e+00, -1.11022302e-16],\n", " [ 0.00000000e+00, 1.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00],\n", " [ 0.00000000e+00, 0.00000000e+00]]), array([[1. , 1. , 0.25 , 0.33333333],\n", " [1. , 1. , 0.5 , 1. ]]), array([[1., 0.],\n", " [0., 0.]]))" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "control.ss(Gmatrix)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What are the true values of those small (10$^{-16}$) values?" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.6" } }, "nbformat": 4, "nbformat_minor": 4 }